package cn.ac.iie.kgmanager.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.apache.commons.lang.exception.ExceptionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * @ClassName LogAspect
 * @Author tjh
 * @Date 18/11/5 上午10:03
 * @Version 1.0
 **/
@Aspect
@Component
@Slf4j
public class LogAspect {
    /**
     *
     */
    @Pointcut(value = "execution(public * cn.ac.iie.kgmanager.controller.*.*(..))")
    public void logPointCut() {

    }

    /**
     * 前置通知 @Before
     * @param joinPoint
     * @return
     * @throws
     */
    @Before("logPointCut()")
    public void doBefore(JoinPoint joinPoint) {
        log.info("--------------doBefore start---------------");

        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(requestAttributes != null) {
            HttpServletRequest request = requestAttributes.getRequest();

            log.info("url:{}", request.getRequestURL());
            log.info("method:{}", request.getMethod());
            log.info("ip:{}", request.getRemoteAddr());
            log.info("params:{}", Arrays.toString(joinPoint.getArgs()));
            log.info("");
        } else {
            log.error("request failed");
        }

        log.info("---------------doBefore end----------------");
    }


    /**
     * 环绕通知 @Around  ， 当然也可以使用 @Before (前置通知)  @After (后置通知)
     * @param joinPoint
     * @return
     * @throws
     */
    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        try {
            long start = System.currentTimeMillis();
            log.info("method executing..........");
            Object result = joinPoint.proceed();
            long end = System.currentTimeMillis();

            log.info("method execute time:{}", end - start);
            log.info("result:{}",result);
            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            log.error("method execute failed:{}", throwable);
        }
        return null;
    }

    /**
     * 后置通知 @After
     * @param
     * @return
     * @throws
     */
    @After(value = "logPointCut()")
    public void doAfter() {

    }

    /**
     *
     * @param obj
     */
    @AfterReturning(returning = "obj", pointcut = "logPointCut()")
    public void doAfterReturn(Object obj) {
        log.info("--------------doAfterReturn---------------");

        if (obj != null) {
            log.info("result:{}", obj.toString());
        } else {
            log.info("no result");
        }

        log.info("------------------------------------------");
    }

    @ExceptionHandler(Exception.class)
    public void handleException(Exception e) {
        log.error(ExceptionUtils.getFullStackTrace(e));
    }


}
